/**
 * 
 */
package cn.buk.tms.dao;

import cn.buk.common.sc.CommonSearchCriteria;
import cn.buk.common.sc.Page;
import cn.buk.tms.entity.misc.DetrInfo;
import cn.buk.tms.entity.misc.DetrInfoFlight;
import cn.buk.common.util.DateUtil;
import cn.buk.tms.entity.misc.DetrInfo_;
import jakarta.persistence.criteria.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import jakarta.transaction.Transactional;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;


/**
 * @author yfdai
 *
 */
@Component
@Transactional
public class DetrDaoImpl extends AbstractDao implements DetrDao {

	private static final Logger logger = LoggerFactory.getLogger(DetrDaoImpl.class);

	/* (non-Javadoc)
	 * @see cn.buk.tms.dao.DetrDao#find(int)
	 */
	@Override
	public DetrInfo getById(int id) {
		DetrInfo detrInfo = em.find(DetrInfo.class, id);
		return detrInfo;
	}

	/* (non-Javadoc)
	 * @see cn.buk.tms.dao.DetrDao#find(cn.buk.qms.SearchDetrCriteria)
	 */
	@Override
	public List<DetrInfo> search(final int enterpriseId, CommonSearchCriteria sc) {
		List<DetrInfo> detrInfos = null;

		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<DetrInfo> detrQuery = cb.createQuery(DetrInfo.class);

		Root<DetrInfo> detrRoot = detrQuery.from(DetrInfo.class);
		detrRoot.alias("o");

		var predicates0 = getPredicates_searchDetr(enterpriseId, sc, cb, detrRoot);

		//****
		detrQuery.where(predicates0.toArray(new Predicate[predicates0.size()]));
		List<Order> orderByes = new ArrayList<>();
		orderByes.add(cb.desc(detrRoot.get("sellDate")));
		orderByes.add(cb.asc(detrRoot.get("tenTicketNo")));
		orderByes.add(cb.desc(detrRoot.get("createDate")));

		detrQuery.orderBy(orderByes);

		//计算根据条件查询得出的数据总数
		//计算根据条件查询得出的数据总数
		CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
		Root<DetrInfo> countRoot = countQuery.from(DetrInfo.class);
		countRoot.alias("o");

		var predicates1 = getPredicates_searchDetr(enterpriseId, sc, cb, countRoot);

		countQuery.select(cb.count(countRoot)).where(predicates1.toArray(new Predicate[predicates1.size()]));
		Long count = em.createQuery(countQuery).getSingleResult();

		int maxResults = count.intValue();
		if (maxResults > 0) {
			Page page = sc.getPage();
			page.setRowCount(maxResults);
			int i = (page.getPageNo() - 1) * page.getPageSize();

			if (i < 0) {
				i = 0;
			}

			try {
				detrInfos = em.createQuery(detrQuery)
								.setFirstResult(i)
								.setMaxResults(page.getPageSize()).getResultList();

			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}

		return detrInfos == null ? new ArrayList<>(): detrInfos;
	}

	private static List<Predicate> getPredicates_searchDetr(int enterpriseId, CommonSearchCriteria sc, CriteriaBuilder cb, Root<DetrInfo> detrRoot) {
		List<Predicate> predicates = new ArrayList<>();

		Predicate predicate = cb.conjunction();
		predicates.add(predicate);

		predicates.add(cb.equal(detrRoot.get(DetrInfo_.enterpriseId), enterpriseId));

		if (sc.getTicketStatus().compareTo("0") == 0) {
			//客票未使用
			Predicate where1 = cb.disjunction();
			where1 = cb.or(where1, cb.equal(detrRoot.get(DetrInfo_.isUsed), "0"));
			where1 = cb.or(where1, cb.equal(detrRoot.get(DetrInfo_.isUsed), "1"));
			predicates.add(where1);
		} else if (sc.getTicketStatus().compareTo("1") == 0) {
			predicates.add(cb.equal(detrRoot.get(DetrInfo_.isUsed), "2"));
		}

		if (sc.getSearchDate() != null && sc.getSearchDate().length() == 10) {
			try {
				predicates.add(cb.equal(detrRoot.get(DetrInfo_.createDate), DateUtil.convertToDate(sc.getSearchDate(), "yyyy-MM-dd")));
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}

		if (sc.getBeginDate() != null) {
			predicates.add(cb.equal(detrRoot.get(DetrInfo_.sellDate), sc.getBeginDate()));
		}

		if (sc.getTicketNo() != null && sc.getTicketNo().trim().length() > 0) {
			predicates.add(cb.like(detrRoot.get(DetrInfo_.ticketNo), "%" + sc.getTicketNo().trim().replaceAll("-", "") + "%"));
		}
		return predicates;
	}

	@SuppressWarnings("unchecked")
	@Override
	public DetrInfo getByTicketNo(int enterpriseId, String ticketNo) {
		List<DetrInfo> detrs = em.createQuery("select o from DetrInfo o where " +
						"o.enterpriseId = :enterpriseId " +
						"and o.ticketNo = :ticketNo " +
						"order by o.id desc")
						.setParameter("enterpriseId", enterpriseId)
						.setParameter("ticketNo", ticketNo)
						.getResultList();

		if (detrs.size() == 0) {
			return null;
		} else {
			DetrInfo detrInfo = detrs.get(0);
			detrInfo.getFlights().size();
			return detrInfo;
		}
	}

	@Override
	public int delete(int id) {
		int returnCode = 0;

		DetrInfo detr = em.find(DetrInfo.class, id);
		if (detr == null) {
      return returnCode;
    }

		em.remove(detr);

		returnCode = 1;

		return returnCode;
	}

    @Override
    public int createDetrInfo(List<DetrInfo> list) {
		int count = 0;
		for (DetrInfo info : list) {
			em.persist(info);
			count++;
		}

		return count;
    }

	public DetrDaoImpl() {
	}

	@Override
  public int refreshDetrInfo(int enterpriseId, int id) {
    return em.createQuery("update DetrInfo o set o.detrDone = null, o.detrDetail = null, o.isUsed = null where o.id = :id and o.enterpriseId = :enterpriseId")
				.setParameter("id", id)
				.setParameter("enterpriseId", enterpriseId)
				.executeUpdate();
  }

  @Override
	public int create(DetrInfo detrInfo) {
		if (detrInfo == null) {
			throw new IllegalArgumentException("detrInfo cannot be null");
		}

		em.persist(detrInfo);

		return detrInfo.getId();
	}

	@Override
	public int update(DetrInfo detrInfo) {
		int returnCode = 0;
		if (detrInfo == null) {
			throw new IllegalArgumentException("detrInfo cannot be null");
		}

		detrInfo.setLastUpdate(DateUtil.getCurDateTime());
		for(DetrInfoFlight flt: detrInfo.getFlights()) {
			flt.setLastUpdate(DateUtil.getCurDateTime());
		}

		em.merge(detrInfo);

		returnCode = detrInfo.getId();

		return returnCode;
	}

}
